package com.wewins.fota.sys.filter;

import com.alibaba.fastjson.JSON;
import com.wewins.fota.bean.bo.TokenUserDetails;
import com.wewins.fota.bean.dto.LoginUserReq;
import com.wewins.fota.bean.dto.LoginUserRes;
import com.wewins.fota.bean.dto.ResponseRst;
import com.wewins.fota.common.constant.AuthConst;
import com.wewins.fota.common.constant.HttpConst;
import com.wewins.fota.sys.token.TokenManager;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;

public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
    private AuthenticationManager authenticationManager;
    private TokenManager tokenManager;

    public TokenLoginFilter(AuthenticationManager authenticationManager, TokenManager tokenManager) {
        this.authenticationManager = authenticationManager;
        this.tokenManager = tokenManager;
        this.setPostOnly(false);
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/auth/login"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        logger.info("start to auth login info.");
        try {
            LoginUserReq user;
            if (HttpMethod.POST.name().equals(request.getMethod())) {
                user = JSON.parseObject(request.getInputStream(), LoginUserReq.class);
            } else {
                user = LoginUserReq.builder().username(request.getParameter("username")).password(request.getParameter("password")).build();
            }
            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), new ArrayList<>()));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException {
        logger.info("login info auth success, start to generate jwt token and return.");
        TokenUserDetails user = (TokenUserDetails) authResult.getPrincipal();
        response.setStatus(HttpConst.STATUS_OK);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        JSON.writeJSONString(response.getWriter(),
                ResponseRst.builder()
                        .status(HttpConst.STATUS_OK)
                        .data(
                                LoginUserRes.builder().
                                        username(user.getUsername())
                                        .token(tokenManager.createToken(user.getUsername())
                                        ).build()
                        ).build()
        );
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException {
        response.setStatus(HttpConst.STATUS_OK);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        JSON.writeJSONString(response.getWriter(),
                ResponseRst.builder()
                        .status(HttpConst.STATUS_UNAUTHORIZED)
                        .message(AuthConst.MSG_FAIL_INVALID_AUTH_INFO)
                        .build()
        );

    }
}
